from .models import *
import os
from rest_framework.response import Response
from AnsibleGUI.settings import MEDIA_ROOT,BASE_DIR
import json
from rest_framework import generics,status
from webapp.serializer import HostListSerializer
from .serializer import *
from common.Uncompress import untar
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.views import APIView
from rest_framework.response import Response
from django.http import JsonResponse
from rest_framework import authentication, permissions
from django.contrib.auth.models import User
from common.KubeClient import KubeClient
from common.KubeJob import KubeJob,create_job_object
# Create your views here.
from common.MultipleFieldLookupMixin import MultipleFieldLookupMixin
from rest_framework.permissions import BasePermission, IsAuthenticated, SAFE_METHODS
from datetime import datetime

###Deployment CRUD Views######
class K8sListView(generics.ListCreateAPIView):
    queryset = Deployment.objects.all()
    serializer_class = K8sSerializer
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['namespace']

    def list(self, request):
        # Note the use of `get_queryset()` instead of `self.queryset`
        queryset = self.get_queryset()
        kube = KubeClient()
        all_response = kube.list_all_namespace_deploy()
        kube_list = []
        for i in all_response.items:
            pod_list = []
            for p in i.spec.template.spec.containers:
                port_list = []
                if p.ports != None:
                    for po in p.ports:
                        port = PodPort(containerPort=po.container_port,hostPort=po.host_port)
                        port_list.append(port)
                pod = Container_Vo(name=p.name,image=p.image,ports=port_list)
                pod_list.append(pod)
            for q in queryset:
                if i.metadata.name == q.deployment_name:
                    i.deployment_type = q.deployment_type
                    i.full_map = q.full_map
                    break
                else:
                    i.deployment_type = "System"
                    i.full_map = ""
            condition_list = []
            for c in i.status.conditions:
                co = Condition_Vo(
                    last_transition_time = c.last_transition_time,
                    last_update_time = c.last_update_time,
                    message = c.message,
                    reason = c.reason,
                    status = c.status,
                    type = c.type
                )
                condition_list.append(co)
            if condition_list[0].status == "True" and condition_list[1].status == "True":
                i.run = "Ready"
            else:
                i.run = "Unhealthy"

            dv = Deployment_Vo(deployment_name=i.metadata.name,
                               namespace=i.metadata.namespace,
                               deployment_type=i.deployment_type,
                               replica=i.spec.replicas,
                               full_map=i.full_map,
                               available_replicas=i.status.available_replicas,
                               collision_count=i.status.collision_count,
                               observed_generation=i.status.observed_generation,
                               ready_replicas=i.status.ready_replicas,
                               updated_replicas=i.status.updated_replicas,
                               labels=i.metadata.labels,
                               pod=pod_list,
                               conditions=condition_list,
                               run=i.run
                               )
            kube_list.append(dv)

        serializer = KubeItemSerializer(kube_list, many=True)
        return Response(serializer.data)

    def create(self,request):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        print(serializer.validated_data['full_map'])
        kc = KubeClient()
        kc.create_namespaced_deploy(namespace=serializer.validated_data['namespace'],dep=serializer.validated_data['full_map'])
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

class K8sDetailView(MultipleFieldLookupMixin,generics.RetrieveUpdateDestroyAPIView):
    queryset = Deployment.objects.all()
    serializer_class = K8sSerializer
    lookup_fields = ['namespace']

    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        kc = KubeClient()
        kc.update_namespaced_deploy(deployment_name=serializer.validated_data['deployment_name'],
                                    namespace=serializer.validated_data['namespace'],
                                    dep=serializer.validated_data['full_map'])
        self.perform_update(serializer)

        if getattr(instance, '_prefetched_objects_cache', None):
            # If 'prefetch_related' has been applied to a queryset, we need to
            # forcibly invalidate the prefetch cache on the instance.
            instance._prefetched_objects_cache = {}
        return Response(serializer.data)

    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        kc = KubeClient()
        kc.delete_namespaced_deploy(deployment_name=instance.deployment_name,
                                    namespace=instance.namespace)
        self.perform_destroy(instance)
        return Response(status=status.HTTP_204_NO_CONTENT)

###Hosts R Views######
class K8sNodeListView(APIView):
    def get(self, request, format=None):
        k1 = KubeClient()
        nodes = k1.list_node()
        serializer = K8sNodeSerializer(nodes,many=True)
        return Response(serializer.data)

class TrainingListView(generics.ListCreateAPIView):
    permission_classes = [IsAuthenticated]
    queryset = K8sJob.objects.all()
    serializer_class = K8sJobSerializer
    filter_backends = [DjangoFilterBackend]

class TrainingDetailView(generics.RetrieveUpdateDestroyAPIView):
    queryset = K8sJob.objects.all()
    serializer_class = K8sJobSerializer

    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)
        return Response(serializer.data)

    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        # kc = KubeClient()
        # kc.delete_namespaced_deploy(deployment_name=instance.deployment_name,
        #                             namespace=instance.namespace)
        self.perform_destroy(instance)
        return Response(status=status.HTTP_204_NO_CONTENT)


def trainjob(obj):
    nodes = TaskRecord.objects.filter(job=obj).order_by('-score')
    print(nodes)
    kj = KubeJob()
    round = 1
    if obj.is_parallel == False:
        for n in nodes:
            if n.status == 1:
                round += 1
            else:
                task_name = obj.name.lower() + '-' + n.hostname + '-' + str(datetime.timestamp(datetime.now()))
                TaskRecord.objects.filter(job=obj, hostname=n.hostname).update(task_name=task_name)
                run_job = create_job_object(round, obj, n, task_name)
                resp = kj.create_job(namespace=obj.namespace, job=run_job)
                print(resp)
                break

class TrainingRun(APIView):
    def get(self, request, *args, **kwargs):
        pk = kwargs.get('uuid')
        obj = K8sJob.objects.get(uuid=pk)
        job = trainjob(obj)
        return JsonResponse({"message": "Task has been executed!", "data": "success"})

class TaskRecordDetailView(MultipleFieldLookupMixin,generics.RetrieveUpdateDestroyAPIView):
    queryset = TaskRecord.objects.all()
    serializer_class = TaskRecordResourceSerializer
    lookup_fields = ["task_name"]


